/**
 * 114静态分析报告
 *
 * Created by nonzhizhong on 2024/06/03.
 */
const fs = require('fs-extra');
const path = require('path');
const compressing = require('compressing');
const moment = require('moment');

const defects = require('../../../defects');
const BaseReporter = require('./../static-analyze-report');
const projectVersions = require('./../../../project-versions');
const functions = require('./../../../functions');
// 导出报告的分类
const exportReportCategory = {
  file: 1, // 按文件分类
  ruleSet: 2, // 按规则集分类
};
class StaticAnalyzeSeariReporter extends BaseReporter {
  constructor(versionId, locale, version = null, project = null, creator = null, outputDir = null, format, filters = {},
    reportCategory, baseDir = null, reportRange = null) {
    reportCategory = exportReportCategory.ruleSet;
    super(versionId, locale, version, project, creator, outputDir, format, filters, reportCategory, baseDir || __dirname, reportRange);
  }

  /**
   * 报告生成
   */
  async generate() {
    const result = {
      cachePath: this.outputDir,
    };
    this.filters.includeDefectId = true;
    this.versionRuleSets = await defects.getDefectTree(this.versionId, this.filters, {
      description: 1,
      wrongExample: 1,
      correctExample: 1,
    });
    const { versionPath } = await this.spliteByProjectVersion((versionDir) => fs.ensureDir(versionDir));
    this.versionDir = path.join(versionPath, `${this.project.projectName}静态分析报告`);

    const rulesData = await this.getVersionDefects({
      description: 1,
      wrongExample: 1,
      correctExample: 1,
    });
    const summary = await this.getSummaryData(rulesData);
    await this.generateReport('file-template', { rulesData, summary }, this.versionDir);
    await this.generateSummary();
    const fileName = `${this.project.projectName}-${this.version.versionName}-${this.getReportName()}-${this.format}.zip`;
    result.reportPath = path.join(this.outputDir, fileName);
    const reportsDir = path.join(this.outputDir, this.project.projectName);
    await compressing.zip.compressDir(reportsDir, result.reportPath);
    return result;
  }

  async getSummaryData(rulesData) {
    const summary = {
      reportTime: moment().format('YYYY年MM月'),
      projectName: this.project.projectName,
      versionName: this.version.versionName,
      language: this.version.language,
      mandatoryKind: 0,
      mandatoryCount: 0,
      advisoryKind: 0,
      advisoryCount: 0,
      summaryKind: 0,
      summaryCount: 0,
    };
    const { numberOfLines, commentLines } = await projectVersions.fileCountInfo(this.versionId, this.version);
    summary.numberOfLines = numberOfLines;
    summary.commentRatio = numberOfLines ? (Math.floor((commentLines / numberOfLines) * 10000) / 100).toString() : '-';
    rulesData.forEach((ruleData) => {
      ruleData.wrongExample = ruleData.wrongExample.split('\n').map((value) => ({
        content: value,
      }));
      ruleData.correctExample = ruleData.correctExample.split('\n').map((value) => ({
        content: value,
      }));
      if (ruleData.ruleCode === 'A-1-13-1') {
        ruleData.hasTable = true;
        ruleData.description = ruleData.description.replace(/<img.*\/>/g, '');
      }
      if (ruleData.level === 1) {
        summary.mandatoryKind += 1;
        summary.mandatoryCount += ruleData.defects.length;
      } else if (ruleData.level === 3) {
        summary.advisoryKind += 1;
        summary.advisoryCount += ruleData.defects.length;
      }
      summary.summaryKind += 1;
      summary.summaryCount += ruleData.defects.length;
    });
    summary.mandatoryRatio = summary.summaryCount ? (Math.floor((summary.mandatoryCount / summary.summaryCount) * 10000) / 100).toString() : '-';
    summary.advisoryRatio = summary.summaryCount ? (Math.floor((summary.advisoryCount / summary.summaryCount) * 10000) / 100).toString() : '-';
    const fanMap = await functions.getFunctionByVersionId(this.versionId, {
      fanIn: 1,
      fanOut: 1,
      cycleComplexity: 1,
      essentialComplexity: 1,
    });
    const fanInfo = [...fanMap.values()];
    const {
      fanInSum, fanOutSum, cycleComplexitySum, essentialComplexitySum,
    } = fanInfo.reduce((init, data) => {
      init.fanInSum += data.fanIn;
      init.fanOutSum += data.fanOut;
      init.cycleComplexitySum += data.cycleComplexity;
      init.essentialComplexitySum += data.essentialComplexity || data.cycleComplexity;
      return init;
    }, {
      fanInSum: 0, fanOutSum: 0, cycleComplexitySum: 0, essentialComplexitySum: 0,
    });
    summary.cycleComplexity = fanInfo.length ? (Math.floor((cycleComplexitySum / fanInfo.length) * 100) / 100).toString() : '-';
    summary.essentialComplexity = fanInfo.length ? (Math.floor((essentialComplexitySum / fanInfo.length) * 100) / 100).toString() : '-';
    summary.averageFanIn = fanInfo.length ? (Math.floor((fanInSum / fanInfo.length) * 100) / 100).toString() : '-';
    summary.averageFanOut = fanInfo.length ? (Math.floor((fanOutSum / fanInfo.length) * 100) / 100).toString() : '-';
    return summary;
  }
}
/**
 * Export model definition object.
 */

module.exports = StaticAnalyzeSeariReporter;
